//This is the main application class.  It extends the Application main class.

#ifndef _MESH_EXAMPLE_H_
#define _MESH_EXAMPLE_H_

#include "../Helix/View/OpenGL/OpenGLSupport.h"
#include "../Helix/Application.h"
#include "../Helix/Window.h"
#include "../Helix/Renderer.h"
#include "../Helix/Updater.h"
#include "../Helix/Input.h"
#include "../Helix/Domain/HelixImage.h"
#include "../Helix/Domain/HelixMesh.h"
#include "../Helix/View/Texture.h"
#include "../Helix/View/OpenGL/OpenGLTexture2D.h"
#include "../Helix/View/RenderHelper.h"

using namespace helix;

//Implements HRenderer and HUpdater
class MeshExample : public Renderer, public Updater
{
private:
	float rotX;
	float rotY;

	Mesh *cube;
	Mesh *cube2;
    
	OpenGLTexture2D *cubeTexture;

	RenderHelper *openGLHelper;

public:

	MeshExample()
	{
		TextureParameters tParams = TextureParameters(TextureParameters::TEXTURE_2D);
		tParams.setMinFilter(TextureParameters::TRILINEAR_SAMPLE_FILTERING);
		tParams.setMaxFilter(TextureParameters::POINT_SAMPLE_FILTERING);
		tParams.setMipMapType(TextureParameters::AUTO_GENERATE_MIP_MAPS);
		tParams.setURepeat(TextureParameters::REPEAT);
		tParams.setVRepeat(TextureParameters::REPEAT);

		//Load the texture
		Image *image= ImageFactory::loadImage("Data/Textures/cube_side.png");
		cubeTexture = new OpenGLTexture2D(image,&tParams);
		ImageFactory::deleteImage(image);

		rotX = 0.0;
		rotY = 0.0;

		float vertData[] = {-1.0f,-1.0f,1.0f,	//vert 0 -- bottom left front corner of cube
							1.0f,-1.0f,1.0f,	//vert 1 -- bottom right front 
							1.0f,1.0f,1.0f,		//vert 2 -- top right front
							-1.0f,1.0f,1.0f,	//vert 3 -- top left front
							-1.0f,-1.0f,-1.0f,	//vert 4 -- bottom left back
							1.0f,-1.0f,-1.0f,	//vert 5 -- bottom right back 
							1.0f,1.0f,-1.0f,	//vert 6 -- top right back
							-1.0f,1.0f,-1.0f};	//vert 7 -- top left back

		float colorData[] = {1.0f,0.0f,0.0f,	//color 0 -- red
							 0.0f,1.0f,0.0f,	//color 1 -- green
							 0.0f,0.0f,1.0f,	//color 2 -- blue
							 1.0f,1.0f,1.0f,	//color 3 -- white
							 0.0f,0.0f,0.0f,	//color 4 -- black
							 1.0f,1.0f,0.0f,	//color 5 -- yellow
							 1.0f,0.0f,1.0f,	//color 6 -- magenta
							 0.0f,1.0f,1.0f};	//color 7 -- cyan

		unsigned int faceData[] = {0,1,2,3,		//Face 0 is the front, verts 0,1,2,3
								   6,7,3,2,		//Face 1 -- top
								   7,4,0,3,		//Face 2 -- left
								   5,6,2,1,		//Face 3 -- right
								   0,4,5,1,		//Face 4 -- bottom
								   4,7,6,5};	//Face 5 -- back

		float texCoordData[] = {0.0f,0.0f,		//vert 0 -- bottom left of texture
								1.0f,0.0f,		//vert 1 -- bottom right
								1.0f,1.0f,		//vert 2 -- top right
								0.0f,1.0f,		//vert 3 -- top left
								1.0f,0.0f,		//vert 4 -- bottom left of texture
								0.0f,0.0f,		//vert 5 -- bottom right
								0.0f,1.0f,		//vert 6 -- top right
								1.0f,1.0f};		//vert 7 -- top left


		
		cube = new Mesh(Mesh::QUAD_MESH,			//Mesh will be made up of quads
						24,							//There are 6 quads with 4 vertices each
						faceData,					//faceData
						24,							//There are 8 vertices with 3 coordinates each
						vertData);					//vertData
		cube->attachDataBuffer(texCoordData,Mesh::TEX_COORD_2D_BUFFER);		//Add a texture coordinate buffer
		cube->attachDataBuffer(colorData,Mesh::RGB_COLOR_BUFFER);		//Add a color buffer

		cube2 = MeshUtil::loadFromHMF("Data/Meshes/cube-24-verts.hmf");

		openGLHelper = Application::getInstance()->window()->getRenderHelper();

		//Set up our one-time opengl stuff
		glEnable(GL_DEPTH_TEST);			//Enable depth testing (faces hidden behind others will not be drawn)
		glClearColor(0.0,0.0,0.0,1.0);		//Set the clear color (color of the background)
		glEnable(GL_TEXTURE_2D);			//Enable texturing
		glBindTexture(GL_TEXTURE_2D,cubeTexture->getId());	//Set our texture as the currently bound one
	}

	~MeshExample()
	{
		delete cubeTexture;
		delete cube;
		MeshUtil::deleteMesh(cube2);
		//Do not delete openGLHelper because it will be deleted by the application when the app is shut down
	}

	virtual void renderScene();
	virtual void update(double dSeconds);
};

#endif
